0.1 Load all of the throw data

# load omnibus dataframe
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
omnibus_df <- read_delim("../data/processed/omnibus/omnibus_raw.csv",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  delim = ",",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  col_types = cols(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    .default = col_double(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    type = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ppid = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    exp_label = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    experiment = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    hand = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    camera_tilt = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    surface_tilt = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    target = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    test_type = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    prior_anim = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    baseline_block = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    task_type = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    surface = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    anim_type = col_factor()
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
) %>% # filter out practice blocks
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(block_num > 4)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# Optionally compute learning rate fits
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# Do the following if learning_rate_df.csv doesn't exist in ../data/processed
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# This takes a loong time
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
if (!file.exists("../data/processed/learning_rate_df.csv")) {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print(Sys.time())
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  apply_exponential_fit <- function(df) {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      summarise(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        ppid = first(ppid),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        experiment = first(experiment),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        test_type = first(test_type),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        exponentialFit = exponentialFit(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
          norm_throw_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
          mode = test_type[1]
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  }
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  init_learning_rates <- omnibus_df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    filter(str_detect(test_type, "init")) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    group_by(ppid, experiment, test_type) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    group_split() %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    future_map(apply_exponential_fit) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    bind_rows() %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    unnest(cols = c("exponentialFit"))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print("done 2 param fits")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print(Sys.time())
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  write_csv(init_learning_rates, "../data/processed/learning_rate_df.csv")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # repeat using exponentialFit_3par
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  apply_exponential_fit_3par <- function(df) {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      summarise(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        ppid = first(ppid),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        experiment = first(experiment),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        test_type = first(test_type),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        exponentialFit = exponentialFit_3par(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
          norm_throw_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
          mode = test_type[1]
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
        )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  }
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  init_learning_rates_3par <- omnibus_df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    filter(str_detect(test_type, "init")) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    group_by(ppid, experiment, test_type) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    group_split() %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    future_map(apply_exponential_fit_3par) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    bind_rows() %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    unnest(cols = c("exponentialFit"))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print("done 3 param fits")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print(Sys.time())
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  write_csv(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    init_learning_rates_3par,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    "../data/processed/learning_rate_df_3par.csv"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
} else {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  print("learning_rate_df.csv exists, loading from file")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  init_learning_rates <- read_csv(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    "../data/processed/learning_rate_df.csv",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    col_types = cols(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      .default = col_double(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      experiment = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      test_type = col_factor()
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  init_learning_rates_3par <- read_csv(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    "../data/processed/learning_rate_df_3par.csv",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    col_types = cols(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      .default = col_double(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      experiment = col_factor(),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      test_type = col_factor()
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
}
[1] "2023-07-06 12:10:02 EDT"
[1] "done 2 param fits"
[1] "2023-07-06 12:12:13 EDT"
[1] "done 3 param fits"
[1] "2023-07-06 12:14:29 EDT"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

1 Visualizing Data (Univariate)

Vectors representing the throw velocity (trace 0) and the velocity applied to the ball (trace 1). The y dimention of the throw is essentially ignored (in reality there is a slight tilt added to account for the tilt of the surface).

test_ppt <- 3
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
test_df <- omnibus_df %>% filter(ppid == test_ppt)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
trial <- 250
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
trial_df <- filter(test_df, trial_num == trial)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
x <- trial_df$flick_velocity_x
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
y <- trial_df$flick_velocity_y
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
z <- trial_df$flick_velocity_z
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
x2 <- trial_df$flick_direction_x * -1
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
y2 <- trial_df$flick_direction_y * -1
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
z2 <- trial_df$flick_direction_z * -1
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# plot both
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- plot_ly(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  x = c(0, x), y = c(0, y), z = c(0, z),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  type = "scatter3d", mode = "lines"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  add_trace(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = c(0, x2), y = c(0, y2), z = c(0, z2),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    type = "scatter3d", mode = "lines"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  layout(scene = list(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    xaxis = list(title = "x", range = c(-2, 2)),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yaxis = list(title = "y", range = c(-1, 3)),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    zaxis = list(title = "z", range = c(-1, 3)),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aspectmode = "cube" # equal aspect ratios
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# Render the plot
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
rm(trial_df)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

note: this is a rotated trial

1.0.1 Distribution of errors

# plot distribution of error_size
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- ggplot(omnibus_df, aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  x = error_size,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  fill = type
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
)) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_histogram(binwidth = .5, alpha = .6) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_minimal() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme(text = element_text(size = 11)) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = c("#f9982c", "#d40000")) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(x = "Error Size (cm)", y = "Count")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

1.0.2 Distribution of throw angles

# plot distribution of error_size
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- ggplot(omnibus_df, aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  x = throw_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  fill = type
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
)) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_histogram(binwidth = 1, alpha = .6) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_minimal() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme(text = element_text(size = 11)) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = c("#f9982c", "#d40000")) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = "Throw Angle (°)", y = "Count"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # dashed lines at 0, -15, -30
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_vline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    xintercept = c(0, -15, -30), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "dashed"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # ticks of 15 degrees
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_x_continuous(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    breaks = c(-30, 0, 30, -60, -90)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

2 ANGULAR DEVIATION Plots (hand angles)

2.0.1 All Trials

Note: Blues = Acceleration Perturbations

# rest of the exps
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- omnibus_df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  group_by(experiment, test_type, trial_num) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  summarise(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    mean_deviation = mean(throw_deviation),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ci_deviation = vector_confint(throw_deviation),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    .groups = "drop"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set up plot
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ggplot(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      x = trial_num, y = mean_deviation, colour = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_classic() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # theme(legend.position = "none") +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = "Trial Number",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    y = "Throw Angle (°)"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # add horizontal lines
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0, -30), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "solid"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(-15), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "dashed"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # set font size to 11
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    text = element_text(size = 11)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # add confidence intervals and data points
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_ribbon(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ymin = mean_deviation - ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ymax = mean_deviation + ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    fill = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  colour = NA, alpha = 0.3
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + 
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_line() + # set colour palette
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_colour_manual(values = pallete_list) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = pallete_list)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
ggplotly(p)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# p
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

2.0.2 Trial sets of interest only

Note: Blues = Acceleration Perturbations

# filter out just the trials of interest
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    test_type != "other"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add a dummy column with repeating sequence
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# NOTE: this can't be combined with above since we are using nrow
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  mutate(dummy_x = rep(1:(nrow(data_per_group) / num_exps),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    length.out = nrow(data_per_group)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set up plot
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ggplot(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      x = dummy_x, y = mean_deviation, colour = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_classic() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # theme(legend.position = "none") +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = "Trial Number",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    y = "Throw Angle (°)"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # add horizontal lines
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0, -30), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "solid"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(-15), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "dashed"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # set colour palette
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_colour_manual(values = pallete_list) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = pallete_list)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add confidence intervals and data points
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
for (unique_test_type in unique(data_per_group$test_type)) {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # get the data for this block
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  to_plot_data <- filter(data_per_group, test_type == unique_test_type)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  p <- p + geom_ribbon(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    data = to_plot_data,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      ymin = mean_deviation - ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      ymax = mean_deviation + ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      fill = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ), colour = NA, alpha = 0.3
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + geom_line(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    data = to_plot_data
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
}
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
ggplotly(p)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

3 NORMALIZED ANGULAR DEVIATIONS (hand angles)

3.0.1 All Trials

Note: Blues = Acceleration Perturbations

# rest of the exps
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- omnibus_df %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  group_by(experiment, test_type, trial_num) %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  summarise(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    mean_deviation = mean(norm_throw_deviation),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ci_deviation = vector_confint(norm_throw_deviation),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    .groups = "drop"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set up plot
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ggplot(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      x = trial_num, y = mean_deviation, colour = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_classic() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # theme(legend.position = "none") +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = "Trial Number",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    y = "Normalized Throw Angle"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add horizontal lines
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- p +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0, 1, 2), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "solid"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0.5, 1.5), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "dashed"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set font size to 11
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- p +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme(text = element_text(size = 11))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add confidence intervals and data points
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- p + geom_ribbon(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ymin = mean_deviation - ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ymax = mean_deviation + ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    fill = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  colour = NA, alpha = 0.3
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
) + geom_line()
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set colour palette
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- p +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_colour_manual(values = pallete_list) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = pallete_list)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
ggplotly(p)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# p
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

3.0.2 Trial sets of interest only

Note: Blues = Acceleration Perturbations

# filter out just the trials of interest
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    test_type != "other"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add a dummy column with repeating sequence
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# NOTE: this can't be combined with above since we are using nrow
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
data_per_group <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  mutate(dummy_x = rep(1:(nrow(data_per_group) / num_exps),
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    length.out = nrow(data_per_group)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ))
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# set up plot
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
p <- data_per_group %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ggplot(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      x = dummy_x, y = mean_deviation, colour = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  theme_classic() +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # theme(legend.position = "none") +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  labs(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    x = "Trial Number",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    y = "Normalized Throw Angle"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # add horizontal lines
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0, 1, 2), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "solid"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  geom_hline(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    yintercept = c(0.5, 1.5), linewidth = 0.4,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    colour = "#CCCCCC", linetype = "dashed"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + # set colour palette
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_colour_manual(values = pallete_list) +
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  scale_fill_manual(values = pallete_list)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
# add confidence intervals and data points
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
for (unique_test_type in unique(data_per_group$test_type)) {
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  # get the data for this block
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  to_plot_data <- filter(data_per_group, test_type == unique_test_type)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  p <- p + geom_ribbon(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    data = to_plot_data,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    aes(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      ymin = mean_deviation - ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      ymax = mean_deviation + ci_deviation,
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
      fill = experiment
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    ), colour = NA, alpha = 0.3
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  ) + geom_line(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    data = to_plot_data
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
}
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
ggplotly(p)
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument

3.1 Exponential Decay Fits for the Learning and Washout Phases

3.1.1 Learning Rates

data_per_ppt <- init_learning_rates %>%
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  filter(
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    experiment != "a_ball_roll_animate_surface",
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
    test_type != "transfer_init"
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) : 
  attempt to use zero-length variable name
data_per_group <- data_per_ppt %>%
  group_by(experiment, test_type) %>%
  summarise(
    mean_learning_rate = mean(exp_fit_lambda),
    ci_learning_rate = vector_confint(exp_fit_lambda),
    mean_high = mean(exp_fit_N0),
    ci_high = vector_confint(exp_fit_N0),
    .groups = "drop"
  )

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_learning_rate, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "Learning Rate"
  ) +
  facet_wrap(
    ~test_type
  ) + # remove all x axis labels
  theme(
  axis.text.x = element_blank()
  ) + # colour legend settings
  guides(
  colour = guide_legend(override.aes = list(alpha = 1))
  ) + # set colour palette
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(
    values = pallete_list
    ) + # add data points
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_lambda
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_learning_rate - ci_learning_rate,
    ymax = mean_learning_rate + ci_learning_rate
  ), alpha = 0.5, lwd = 2) +
  geom_point()

ggplotly(p)
# p

3.1.2 High Points (Asymptotes or Starts)

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_high, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "High Point"
  ) +
  facet_wrap(~test_type) + # remove all x axis labels
  theme(axis.text.x = element_blank()) +
  # for the colour legend, only show the first 7
  # Note this doesn't work for the plotly plot
  guides(
  colour = guide_legend(override.aes = list(alpha = 1))
  )+ # set colour palette
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list) +
  # add data points
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_N0
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_high - ci_high,
    ymax = mean_high + ci_high
  ), alpha = 0.5, lwd = 2) +
  geom_point()

ggplotly(p)
# p

For washout: The CUED accel + curved have a lower starting point (therefore – cue works). VMR group has slightly lower. When comparing everything with a high starting point, the ACCEL group has a much FASTER learning rate.

3.1.3 High Points v Learning Rates

# Compare learning rates and high points
p <- data_per_ppt %>%
  ggplot(
    aes(x = exp_fit_lambda, y = exp_fit_N0, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = "Learning Rate",
    y = "High Point"
  ) +
  facet_wrap(~test_type) +
  geom_point() +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)

3.2 Exponential Decay Fits for the Transfer Phase

3.2.1 Learning Rates

data_per_ppt <- init_learning_rates_3par %>%
  filter(
    experiment != "a_ball_roll_animate_surface",
    test_type == "transfer_init"
  )
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) : 
  attempt to use zero-length variable name
data_per_group <- data_per_ppt %>%
  group_by(experiment, test_type) %>%
  summarise(
    mean_learning_rate = mean(exp_fit_lambda),
    ci_learning_rate = vector_confint(exp_fit_lambda),
    mean_high = mean(exp_fit_N0),
    ci_high = vector_confint(exp_fit_N0),
    mean_low = mean(exp_fit_displace),
    ci_low = vector_confint(exp_fit_displace),
    .groups = "drop"
  )

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_learning_rate, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "Learning Rate"
  ) +
  facet_wrap(~test_type) +
  # remove all x axis labels
  theme(axis.text.x = element_blank()) +
  # for the colour legend, only show the first 7
  # Note this doesn't work for the plotly plot
  guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  # add data points
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_lambda
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_learning_rate - ci_learning_rate,
    ymax = mean_learning_rate + ci_learning_rate
  ), alpha = 0.5, lwd = 2) +
  geom_point() +
  # set colour palette
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

3.2.2 High Points (Asymptotes)

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_high, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "High Point (Asymptotes)"
  ) +
  facet_wrap(~test_type) +
  # remove all x axis labels
  theme(axis.text.x = element_blank()) +
  # for the colour legend, only show the first 7
  # Note this doesn't work for the plotly plot
  guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  # add data points
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_N0
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_high - ci_high,
    ymax = mean_high + ci_high
  ), alpha = 0.5, lwd = 2) +
  geom_point() +
  # set colour palette
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

3.2.3 Low Points (Starts)

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_low, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "Low Point (Starts)"
  ) +
  facet_wrap(~test_type)

# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())

# for the colour legend, only show the first 7
# Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))

# add data points
p <- p +
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_displace
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_low - ci_low,
    ymax = mean_low + ci_low
  ), alpha = 0.5, lwd = 2) +
  geom_point()

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

When transferring, what happens?

3.2.4 Correlations within the 3 variables above

# 3d plot of learning rates, high points, and low points
# filter out just the washout trials for now
data_per_ppt <- init_learning_rates_3par %>%
  filter(test_type == "transfer_init")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) : 
  attempt to use zero-length variable name
p <- plot_ly(type = "scatter3d", mode = "markers")

for (experiment_ in unique(data_per_ppt$experiment)) {
  # get the data for this block
  to_plot_data <- filter(data_per_ppt, experiment == experiment_)

  p <- p %>%
    add_trace(
      x = to_plot_data$exp_fit_lambda,
      y = to_plot_data$exp_fit_N0,
      z = to_plot_data$exp_fit_displace,
      color = I(pallete_list[experiment_]),
      name = experiment_
    )
}

# Axes names
p <- p %>% layout(
  scene =
    (list(
      xaxis = list(title = "Learning Rate"),
      yaxis = list(title = "High Point"),
      zaxis = list(title = "Low Point"),
      aspectmode = "cube" # equal aspect ratios
    ))
)

p
  • We might want to test if data points cluster differently depending on the experiment conditions.
  • Note: It is a good idea to do some EDA to check if all 3 dimensions are required. Correlation matrix?

3.2.5 Inidividual Data within 1 group

### Error Size ###

# rest of the exps
data_per_ppt <- omnibus_df %>%
  filter(experiment == "accel_uncued", test_type == "washout_init")
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) : 
  attempt to use zero-length variable name
# set up plot
p <- data_per_ppt %>%
  ggplot(
    aes(
      x = trial_num, y = norm_throw_deviation, colour = ppid
    )
  ) +
  theme_classic() +
  # theme(legend.position = "none") +
  labs(
    x = "Trial Number",
    y = "Normalized Throw Angle"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 1, 2), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(0.5, 1.5), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add confidence intervals and data points
p <- p + geom_line()

ggplotly(p)

# p

4 ERROR SIZE

Note: Blues = Acceleration Perturbations

# original experiments only
data_per_group <- omnibus_df %>%
  filter(exp_label == "original_exps" | exp_label == "curved_path") %>%
  group_by(experiment, test_type, trial_num) %>%
  summarise(
    mean_deviation = mean(error_size),
    ci_deviation = vector_confint(error_size),
    .groups = "drop"
  )

# set up plot
p <- data_per_group %>%
  ggplot(
    aes(
      x = trial_num, y = mean_deviation, colour = experiment
    )
  ) +
  theme_classic() +
  # theme(legend.position = "none") +
  labs(
    x = "Trial Number",
    y = "Absolute Target Error (cm)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 40), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(20), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# add confidence intervals and data points
p <- p + geom_ribbon(
  aes(
    ymin = mean_deviation - ci_deviation,
    ymax = mean_deviation + ci_deviation,
    fill = experiment
  ),
  colour = NA, alpha = 0.3
) + geom_line()

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)

# p

visible vs non-visible tilt doesn’t affect the 15-degree rotation condition. But affects all other conditions. So 15-degree rotation

4.0.1 Trial sets of interest only

Note: Blues = Acceleration Perturbations

# filter out just the trials of interest
data_per_group <- data_per_group %>%
  filter(
    test_type != "other"
  )
# add a dummy column with repeating sequence
# NOTE: this can't be combined with above since we are using nrow
data_per_group <- data_per_group %>%
  mutate(dummy_x = rep(1:(nrow(data_per_group) / num_exps),
    length.out = nrow(data_per_group)
  ))

# set up plot
p <- data_per_group %>%
  ggplot(
    aes(
      x = dummy_x, y = mean_deviation, colour = experiment
    )
  ) +
  theme_classic() +
  # theme(legend.position = "none") +
  labs(
    x = "Trial Number",
    y = "Absolute Target Error (cm)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, 40), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(20), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add confidence intervals and data points
for (unique_test_type in unique(data_per_group$test_type)) {
  # get the data for this block
  to_plot_data <- filter(data_per_group, test_type == unique_test_type)

  p <- p + geom_ribbon(
    data = to_plot_data,
    aes(
      ymin = mean_deviation - ci_deviation,
      ymax = mean_deviation + ci_deviation,
      fill = experiment
    ), colour = NA, alpha = 0.3
  ) + geom_line(
    data = to_plot_data
  )
}

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)

5 Animated Surface Follow-up

5.0.1 Plot ANGULAR DEVIATIONS (hand angles)

# isolate animate_surface exp
data_per_group <- omnibus_df %>%
  filter(exp_label == "animate_surface") %>%
  group_by(prior_anim, block_num, trial_num_in_block, trial_num) %>%
  summarise(
    mean_deviation = mean(throw_deviation),
    ci_deviation = vector_confint(throw_deviation)
  )

# order the factors for assigning colour pallets
data_per_group$prior_anim <- factor(
  data_per_group$prior_anim,
  levels = c(
    "none", "half_anim", "full_anim"
  )
)

# set up plot
p <- data_per_group %>%
  ggplot(
    aes(
      x = trial_num, y = mean_deviation,
      ymin = mean_deviation - ci_deviation,
      ymax = mean_deviation + ci_deviation
    )
  ) +
  theme_classic() +
  # theme(legend.position = "none") +
  labs(
    x = "Trial Number",
    y = "Throw Angle (°)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, -30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(-15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# set font size to 11
p <- p +
  theme(text = element_text(size = 11))

# repeat for prior_anim == "half", "full" and "wait"
for (unique_prior_anim in unique(data_per_group$prior_anim)) {
  # get the data for this block
  to_plot_data <- filter(data_per_group, prior_anim == unique_prior_anim)
  # loop through the unique blocks in to_plot_data
  for (block in unique(to_plot_data$block_num)) {
    # get the data for this block
    block_data <- filter(to_plot_data, block_num == block)
    # add the data, use the pallete_list to get the colour
    p <- p + geom_ribbon(
      data = block_data,
      aes(fill = prior_anim),
      colour = NA, alpha = 0.3
    ) + geom_line(
      data = block_data,
      aes(colour = prior_anim)
    )
  }
}

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

5.0.2 Washout trials after half VS full animations

# first, isolate the data
data_per_ppt_anim <- omnibus_df %>%
  filter(
    exp_label == "animate_surface",
    baseline_block == FALSE,
    test_type == "washout_anim"
  ) %>%
  group_by(ppid, prior_anim, trial_num_in_block) %>%
  summarise(
    ppt_median_deviation = median(throw_deviation),
    .groups = "drop"
  ) %>% # prior_anim rename to experiment (to match the other comparisons)
  mutate(
    experiment = prior_anim,
    throw_deviation = ppt_median_deviation
  ) %>%
  select(-prior_anim, -ppt_median_deviation)

data_per_group <- data_per_ppt_anim %>%
  group_by(experiment, trial_num_in_block) %>%
  summarise(
    mean_deviation = mean(throw_deviation),
    ci_deviation = vector_confint(throw_deviation),
    n = n()
  )

# set up plot
p <- data_per_group %>%
  ggplot(
    aes(
      x = trial_num_in_block, y = mean_deviation,
      colour = experiment, fill = experiment
    )
  ) +
  theme_classic() +
  # theme(legend.position = "none") +
  labs(
    x = "Trial Number in Block",
    y = "Throw Angle (°)"
  )

# add horizontal lines
p <- p +
  geom_hline(
    yintercept = c(0, -30), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "solid"
  ) +
  geom_hline(
    yintercept = c(-15), linewidth = 0.4,
    colour = "#CCCCCC", linetype = "dashed"
  )

# add data points
p <- p +
  geom_ribbon(
    aes(
      ymin = mean_deviation - ci_deviation,
      ymax = mean_deviation + ci_deviation
    ),
    colour = NA, alpha = 0.3
  ) +
  geom_line()

# add washout_init from the 30-degree rotation condition
data_per_ppt_30 <- omnibus_df %>%
  filter(
    experiment %in% c("rot30_cued_tilt", "rot30_uncued"),
    test_type == "washout_init",
    trial_num_in_block <= 8
  ) %>%
  select(ppid, trial_num_in_block, experiment, throw_deviation)

data_per_group_30 <- data_per_ppt_30 %>%
  group_by(experiment, trial_num_in_block) %>%
  summarise(
    mean_deviation = mean(throw_deviation),
    ci_deviation = vector_confint(throw_deviation),
    n = n(),
    .groups = "drop"
  )

# add data points
p <- p +
  geom_ribbon(
    data = data_per_group_30,
    aes(
      ymin = mean_deviation - ci_deviation,
      ymax = mean_deviation + ci_deviation,
      fill = experiment
    ),
    colour = NA, alpha = 0.3
  ) +
  geom_line(
    data = data_per_group_30,
    aes(
      colour = experiment
    )
  )

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# rbind data_per_ppt_anim and data_per_ppt_30
anim_comparison_df <- rbind(
  data_per_ppt_anim,
  data_per_ppt_30
)

# remove data_per_ppt_anim and data_per_ppt_30
rm(data_per_ppt_anim, data_per_ppt_30)

# Optionally compute learning rate fits
# Do if learning_rate_df_anim.csv doesn't exist in ../data/processed
if (!file.exists("../data/processed/learning_rate_df_anim.csv")) {
  print(Sys.time())
  apply_exponential_fit <- function(df) {
    df %>%
      summarise(
        ppid = first(ppid),
        experiment = first(experiment),
        exponentialFit = exponentialFit(throw_deviation,
          mode = "washout_init"
        )
      )
  }

  anim_learning_rates <- anim_comparison_df %>%
    group_by(ppid, experiment) %>%
    group_split() %>%
    future_map(apply_exponential_fit) %>%
    bind_rows() %>%
    unnest(cols = c("exponentialFit"))

  print("done 2 param fits")
  print(Sys.time())

  write_csv(
    anim_learning_rates,
    "../data/processed/learning_rate_df_anim.csv"
  )
} else {
  anim_learning_rates <- read_csv(
    "../data/processed/learning_rate_df_anim.csv",
    col_types = cols(
      .default = col_double(),
      ppid = col_factor(),
      experiment = col_factor()
    )
  )
}
[1] "2023-07-06 12:14:59 EDT"
[1] "done 2 param fits"
[1] "2023-07-06 12:15:25 EDT"

5.0.3 Learning Rates

data_per_ppt <- anim_learning_rates
Error in exists(cacheKey, where = .rs.WorkingDataEnv, inherits = FALSE) : 
  invalid first argument
Error in assign(cacheKey, frame, .rs.CachedDataEnv) : 
  attempt to use zero-length variable name
data_per_group <- data_per_ppt %>%
  group_by(experiment) %>%
  summarise(
    mean_learning_rate = mean(exp_fit_lambda),
    ci_learning_rate = vector_confint(exp_fit_lambda),
    mean_high = mean(exp_fit_N0),
    ci_high = vector_confint(exp_fit_N0),
    .groups = "drop"
  )

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_learning_rate, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "Learning Rate"
  )

# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())

# for the colour legend, only show the first 7
# Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))

# add data points
p <- p +
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_lambda
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_learning_rate - ci_learning_rate,
    ymax = mean_learning_rate + ci_learning_rate
  ), alpha = 0.5, lwd = 2) +
  geom_point()

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

5.0.4 High Points (Starts)

p <- data_per_group %>%
  ggplot(
    aes(x = experiment, y = mean_high, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = NULL,
    y = "Start Point"
  )

# remove all x axis labels
p <- p + theme(axis.text.x = element_blank())

# for the colour legend, only show the first 7
# Note this doesn't work for the plotly plot
p <- p + guides(colour = guide_legend(override.aes = list(alpha = 1)))

# add data points
p <- p +
  geom_beeswarm(
    data = data_per_ppt,
    aes(
      y = exp_fit_N0
    ),
    alpha = 0.1,
    size = 1
  ) +
  geom_linerange(aes(
    ymin = mean_high - ci_high,
    ymax = mean_high + ci_high
  ), alpha = 0.5, lwd = 2) +
  geom_point()

# set colour palette
p <- p +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)
# p

5.0.5 High Points v Learning Rates

# Compare learning rates and high points
p <- data_per_ppt %>%
  ggplot(
    aes(x = exp_fit_lambda, y = exp_fit_N0, colour = experiment)
  ) +
  theme_classic() +
  labs(
    x = "Learning Rate",
    y = "High Point (Starts)"
  ) +
  geom_point() +
  scale_colour_manual(values = pallete_list) +
  scale_fill_manual(values = pallete_list)

ggplotly(p)

6 Deprecated (Don’t Run)

6.1 Success manifolds

6.1.1 Without any tilts

plot_success_manifold_no_tilt()

6.1.2 With tilt present

plot_success_manifold_tilt()
LS0tDQp0aXRsZTogIkJpbGxpYXJkcyBhbmQgVGlsdHMgQW5hbHlzaXMgTm90ZWJvb2siDQphdXRob3I6ICJTaGFuYWF0aGFuYW4gTW9kY2hhbGluZ2FtIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kcm0obGlzdCA9IGxzKCkpICMgY2xlYW4gZW52aXJvbm1lbnQNCg0Kc291cmNlKCIuLi9zcmMvaGVscGVyX2Z1bmNzLlIiKQ0Kc291cmNlKCIuLi9zY3JpcHRzL2ZpZ3VyZV9mdW5jcy5SIikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ2JlZXN3YXJtKQ0KbGlicmFyeShleikgIyBmb3IgQU5PVkFzDQpsaWJyYXJ5KGVmZmVjdHNpemUpICMgZm9yIGV0YS1zcXVhcmVkDQpsaWJyYXJ5KHBsb3RseSkNCg0KbGlicmFyeShmdXJycikNCnBsYW4obXVsdGlzZXNzaW9uKQ0KDQpvcHRpb25zKGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSkNCg0KIyB2YXJzDQpvbW5pYnVzX3BhdGggPC0gIi4uL2RhdGEvcHJvY2Vzc2VkL29tbmlidXMvb21uaWJ1c19yYXcuY3N2Ig0KDQojIGNvbnZlcnQgdGhlIGFib3ZlIGludG8gYSBsaXN0DQpwYWxsZXRlX2xpc3QgPC0gYygNCiAgInJvdDMwX2N1ZWRfdGlsdCIgPSAiI2Q0MDAwMCIsDQogICJyb3QzMF91bmN1ZWQiID0gIiNmOTk4MmMiLA0KICAiYWNjZWxfY3VlZF90aWx0IiA9ICIjMDc1MDliIiwNCiAgImFjY2VsX3VuY3VlZCIgPSAiIzVmYjY5NiIsDQogICJjdXJ2ZWRfY3VlZF90aWx0IiA9ICIjMmI1NzQ3IiwNCiAgInJvdDE1X2N1ZWRfdGlsdCIgPSAiIzc3MDIwMiIsDQogICJyb3QxNV91bmN1ZWQiID0gIiNhNzYzMTUiLA0KICAibm9uZSIgPSAiI2Y5OTgyYyIsDQogICJoYWxmX2FuaW0iID0gIiM1ZmI2OTYiLA0KICAiZnVsbF9hbmltIiA9ICIjMDc1MDliIiwNCiAgIndhaXQiID0gIiNhNzYzMTUiDQopDQoNCm51bV9leHBzIDwtIDcNCmBgYA0KDQoNCg0KIyMgTG9hZCBhbGwgb2YgdGhlIHRocm93IGRhdGENCmBgYHtyfQ0KIyBsb2FkIG9tbmlidXMgZGF0YWZyYW1lDQpvbW5pYnVzX2RmIDwtIHJlYWRfZGVsaW0oIi4uL2RhdGEvcHJvY2Vzc2VkL29tbmlidXMvb21uaWJ1c19yYXcuY3N2IiwNCiAgZGVsaW0gPSAiLCIsDQogIGNvbF90eXBlcyA9IGNvbHMoDQogICAgLmRlZmF1bHQgPSBjb2xfZG91YmxlKCksDQogICAgdHlwZSA9IGNvbF9mYWN0b3IoKSwNCiAgICBwcGlkID0gY29sX2ZhY3RvcigpLA0KICAgIGV4cF9sYWJlbCA9IGNvbF9mYWN0b3IoKSwNCiAgICBleHBlcmltZW50ID0gY29sX2ZhY3RvcigpLA0KICAgIGhhbmQgPSBjb2xfZmFjdG9yKCksDQogICAgY2FtZXJhX3RpbHQgPSBjb2xfZmFjdG9yKCksDQogICAgc3VyZmFjZV90aWx0ID0gY29sX2ZhY3RvcigpLA0KICAgIHRhcmdldCA9IGNvbF9mYWN0b3IoKSwNCiAgICB0ZXN0X3R5cGUgPSBjb2xfZmFjdG9yKCksDQogICAgcHJpb3JfYW5pbSA9IGNvbF9mYWN0b3IoKSwNCiAgICBiYXNlbGluZV9ibG9jayA9IGNvbF9mYWN0b3IoKSwNCiAgICB0YXNrX3R5cGUgPSBjb2xfZmFjdG9yKCksDQogICAgc3VyZmFjZSA9IGNvbF9mYWN0b3IoKSwNCiAgICBhbmltX3R5cGUgPSBjb2xfZmFjdG9yKCkNCiAgKQ0KKSAlPiUgIyBmaWx0ZXIgb3V0IHByYWN0aWNlIGJsb2Nrcw0KICBmaWx0ZXIoYmxvY2tfbnVtID4gNCkNCg0KIyBPcHRpb25hbGx5IGNvbXB1dGUgbGVhcm5pbmcgcmF0ZSBmaXRzDQojIERvIHRoZSBmb2xsb3dpbmcgaWYgbGVhcm5pbmdfcmF0ZV9kZi5jc3YgZG9lc24ndCBleGlzdCBpbiAuLi9kYXRhL3Byb2Nlc3NlZA0KIyBUaGlzIHRha2VzIGEgbG9vbmcgdGltZQ0KaWYgKCFmaWxlLmV4aXN0cygiLi4vZGF0YS9wcm9jZXNzZWQvbGVhcm5pbmdfcmF0ZV9kZi5jc3YiKSkgew0KICBwcmludChTeXMudGltZSgpKQ0KICBhcHBseV9leHBvbmVudGlhbF9maXQgPC0gZnVuY3Rpb24oZGYpIHsNCiAgICBkZiAlPiUNCiAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgcHBpZCA9IGZpcnN0KHBwaWQpLA0KICAgICAgICBleHBlcmltZW50ID0gZmlyc3QoZXhwZXJpbWVudCksDQogICAgICAgIHRlc3RfdHlwZSA9IGZpcnN0KHRlc3RfdHlwZSksDQogICAgICAgIGV4cG9uZW50aWFsRml0ID0gZXhwb25lbnRpYWxGaXQoDQogICAgICAgICAgbm9ybV90aHJvd19kZXZpYXRpb24sDQogICAgICAgICAgbW9kZSA9IHRlc3RfdHlwZVsxXQ0KICAgICAgICApDQogICAgICApDQogIH0NCg0KICBpbml0X2xlYXJuaW5nX3JhdGVzIDwtIG9tbmlidXNfZGYgJT4lDQogICAgZmlsdGVyKHN0cl9kZXRlY3QodGVzdF90eXBlLCAiaW5pdCIpKSAlPiUNCiAgICBncm91cF9ieShwcGlkLCBleHBlcmltZW50LCB0ZXN0X3R5cGUpICU+JQ0KICAgIGdyb3VwX3NwbGl0KCkgJT4lDQogICAgZnV0dXJlX21hcChhcHBseV9leHBvbmVudGlhbF9maXQpICU+JQ0KICAgIGJpbmRfcm93cygpICU+JQ0KICAgIHVubmVzdChjb2xzID0gYygiZXhwb25lbnRpYWxGaXQiKSkNCg0KICBwcmludCgiZG9uZSAyIHBhcmFtIGZpdHMiKQ0KICBwcmludChTeXMudGltZSgpKQ0KDQogIHdyaXRlX2Nzdihpbml0X2xlYXJuaW5nX3JhdGVzLCAiLi4vZGF0YS9wcm9jZXNzZWQvbGVhcm5pbmdfcmF0ZV9kZi5jc3YiKQ0KDQogICMgcmVwZWF0IHVzaW5nIGV4cG9uZW50aWFsRml0XzNwYXINCiAgYXBwbHlfZXhwb25lbnRpYWxfZml0XzNwYXIgPC0gZnVuY3Rpb24oZGYpIHsNCiAgICBkZiAlPiUNCiAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgcHBpZCA9IGZpcnN0KHBwaWQpLA0KICAgICAgICBleHBlcmltZW50ID0gZmlyc3QoZXhwZXJpbWVudCksDQogICAgICAgIHRlc3RfdHlwZSA9IGZpcnN0KHRlc3RfdHlwZSksDQogICAgICAgIGV4cG9uZW50aWFsRml0ID0gZXhwb25lbnRpYWxGaXRfM3BhcigNCiAgICAgICAgICBub3JtX3Rocm93X2RldmlhdGlvbiwNCiAgICAgICAgICBtb2RlID0gdGVzdF90eXBlWzFdDQogICAgICAgICkNCiAgICAgICkNCiAgfQ0KDQogIGluaXRfbGVhcm5pbmdfcmF0ZXNfM3BhciA8LSBvbW5pYnVzX2RmICU+JQ0KICAgIGZpbHRlcihzdHJfZGV0ZWN0KHRlc3RfdHlwZSwgImluaXQiKSkgJT4lDQogICAgZ3JvdXBfYnkocHBpZCwgZXhwZXJpbWVudCwgdGVzdF90eXBlKSAlPiUNCiAgICBncm91cF9zcGxpdCgpICU+JQ0KICAgIGZ1dHVyZV9tYXAoYXBwbHlfZXhwb25lbnRpYWxfZml0XzNwYXIpICU+JQ0KICAgIGJpbmRfcm93cygpICU+JQ0KICAgIHVubmVzdChjb2xzID0gYygiZXhwb25lbnRpYWxGaXQiKSkNCg0KICBwcmludCgiZG9uZSAzIHBhcmFtIGZpdHMiKQ0KICBwcmludChTeXMudGltZSgpKQ0KDQogIHdyaXRlX2NzdigNCiAgICBpbml0X2xlYXJuaW5nX3JhdGVzXzNwYXIsDQogICAgIi4uL2RhdGEvcHJvY2Vzc2VkL2xlYXJuaW5nX3JhdGVfZGZfM3Bhci5jc3YiDQogICkNCn0gZWxzZSB7DQogIHByaW50KCJsZWFybmluZ19yYXRlX2RmLmNzdiBleGlzdHMsIGxvYWRpbmcgZnJvbSBmaWxlIikNCiAgaW5pdF9sZWFybmluZ19yYXRlcyA8LSByZWFkX2NzdigNCiAgICAiLi4vZGF0YS9wcm9jZXNzZWQvbGVhcm5pbmdfcmF0ZV9kZi5jc3YiLA0KICAgIGNvbF90eXBlcyA9IGNvbHMoDQogICAgICAuZGVmYXVsdCA9IGNvbF9kb3VibGUoKSwNCiAgICAgIGV4cGVyaW1lbnQgPSBjb2xfZmFjdG9yKCksDQogICAgICB0ZXN0X3R5cGUgPSBjb2xfZmFjdG9yKCkNCiAgICApDQogICkNCg0KICBpbml0X2xlYXJuaW5nX3JhdGVzXzNwYXIgPC0gcmVhZF9jc3YoDQogICAgIi4uL2RhdGEvcHJvY2Vzc2VkL2xlYXJuaW5nX3JhdGVfZGZfM3Bhci5jc3YiLA0KICAgIGNvbF90eXBlcyA9IGNvbHMoDQogICAgICAuZGVmYXVsdCA9IGNvbF9kb3VibGUoKSwNCiAgICAgIGV4cGVyaW1lbnQgPSBjb2xfZmFjdG9yKCksDQogICAgICB0ZXN0X3R5cGUgPSBjb2xfZmFjdG9yKCkNCiAgICApDQogICkNCn0NCmBgYA0KDQojIFZpc3VhbGl6aW5nIERhdGEgKFVuaXZhcmlhdGUpDQpWZWN0b3JzIHJlcHJlc2VudGluZyB0aGUgdGhyb3cgdmVsb2NpdHkgKHRyYWNlIDApIGFuZCB0aGUgdmVsb2NpdHkgYXBwbGllZCB0byB0aGUgYmFsbCAodHJhY2UgMSkuIFRoZSB5IGRpbWVudGlvbiBvZiB0aGUgdGhyb3cgaXMgZXNzZW50aWFsbHkgaWdub3JlZCAoaW4gcmVhbGl0eSB0aGVyZSBpcyBhIHNsaWdodCB0aWx0IGFkZGVkIHRvIGFjY291bnQgZm9yIHRoZSB0aWx0IG9mIHRoZSBzdXJmYWNlKS4NCmBgYHtyfQ0KdGVzdF9wcHQgPC0gMw0KDQp0ZXN0X2RmIDwtIG9tbmlidXNfZGYgJT4lIGZpbHRlcihwcGlkID09IHRlc3RfcHB0KQ0KDQoNCnRyaWFsIDwtIDI1MA0KdHJpYWxfZGYgPC0gZmlsdGVyKHRlc3RfZGYsIHRyaWFsX251bSA9PSB0cmlhbCkNCg0KeCA8LSB0cmlhbF9kZiRmbGlja192ZWxvY2l0eV94DQp5IDwtIHRyaWFsX2RmJGZsaWNrX3ZlbG9jaXR5X3kNCnogPC0gdHJpYWxfZGYkZmxpY2tfdmVsb2NpdHlfeg0KDQp4MiA8LSB0cmlhbF9kZiRmbGlja19kaXJlY3Rpb25feCAqIC0xDQp5MiA8LSB0cmlhbF9kZiRmbGlja19kaXJlY3Rpb25feSAqIC0xDQp6MiA8LSB0cmlhbF9kZiRmbGlja19kaXJlY3Rpb25feiAqIC0xDQoNCiMgcGxvdCBib3RoDQpwIDwtIHBsb3RfbHkoDQogIHggPSBjKDAsIHgpLCB5ID0gYygwLCB5KSwgeiA9IGMoMCwgeiksDQogIHR5cGUgPSAic2NhdHRlcjNkIiwgbW9kZSA9ICJsaW5lcyINCikgJT4lDQogIGFkZF90cmFjZSgNCiAgICB4ID0gYygwLCB4MiksIHkgPSBjKDAsIHkyKSwgeiA9IGMoMCwgejIpLA0KICAgIHR5cGUgPSAic2NhdHRlcjNkIiwgbW9kZSA9ICJsaW5lcyINCiAgKSAlPiUNCiAgbGF5b3V0KHNjZW5lID0gbGlzdCgNCiAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAieCIsIHJhbmdlID0gYygtMiwgMikpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJ5IiwgcmFuZ2UgPSBjKC0xLCAzKSksDQogICAgemF4aXMgPSBsaXN0KHRpdGxlID0gInoiLCByYW5nZSA9IGMoLTEsIDMpKSwNCiAgICBhc3BlY3Rtb2RlID0gImN1YmUiICMgZXF1YWwgYXNwZWN0IHJhdGlvcw0KICApKQ0KDQojIFJlbmRlciB0aGUgcGxvdA0KcA0KDQpybSh0cmlhbF9kZikNCmBgYA0Kbm90ZTogdGhpcyBpcyBhIHJvdGF0ZWQgdHJpYWwNCg0KIyMjIERpc3RyaWJ1dGlvbiBvZiBlcnJvcnMNCmBgYHtyfQ0KIyBwbG90IGRpc3RyaWJ1dGlvbiBvZiBlcnJvcl9zaXplDQpwIDwtIGdncGxvdChvbW5pYnVzX2RmLCBhZXMoDQogIHggPSBlcnJvcl9zaXplLA0KICBmaWxsID0gdHlwZQ0KKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC41LCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjZjk5ODJjIiwgIiNkNDAwMDAiKSkgKw0KICBsYWJzKHggPSAiRXJyb3IgU2l6ZSAoY20pIiwgeSA9ICJDb3VudCIpDQoNCnANCmBgYA0KDQojIyMgRGlzdHJpYnV0aW9uIG9mIHRocm93IGFuZ2xlcw0KYGBge3J9DQojIHBsb3QgZGlzdHJpYnV0aW9uIG9mIGVycm9yX3NpemUNCnAgPC0gZ2dwbG90KG9tbmlidXNfZGYsIGFlcygNCiAgeCA9IHRocm93X2RldmlhdGlvbiwNCiAgZmlsbCA9IHR5cGUNCikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBhbHBoYSA9IC42KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjZjk5ODJjIiwgIiNkNDAwMDAiKSkgKw0KICBsYWJzKA0KICAgIHggPSAiVGhyb3cgQW5nbGUgKMKwKSIsIHkgPSAiQ291bnQiDQogICkgKyAjIGRhc2hlZCBsaW5lcyBhdCAwLCAtMTUsIC0zMA0KICBnZW9tX3ZsaW5lKA0KICAgIHhpbnRlcmNlcHQgPSBjKDAsIC0xNSwgLTMwKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApICsgIyB0aWNrcyBvZiAxNSBkZWdyZWVzDQogIHNjYWxlX3hfY29udGludW91cygNCiAgICBicmVha3MgPSBjKC0zMCwgMCwgMzAsIC02MCwgLTkwKQ0KICApDQoNCnANCmBgYA0KDQojIEFOR1VMQVIgREVWSUFUSU9OIFBsb3RzIChoYW5kIGFuZ2xlcykNCiMjIyBBbGwgVHJpYWxzDQpOb3RlOiBCbHVlcyA9IEFjY2VsZXJhdGlvbiBQZXJ0dXJiYXRpb25zDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQojIHJlc3Qgb2YgdGhlIGV4cHMNCmRhdGFfcGVyX2dyb3VwIDwtIG9tbmlidXNfZGYgJT4lDQogIGZpbHRlcihleHBfbGFiZWwgPT0gIm9yaWdpbmFsX2V4cHMiIHwgZXhwX2xhYmVsID09ICJjdXJ2ZWRfcGF0aCIpICU+JQ0KICBncm91cF9ieShleHBlcmltZW50LCB0ZXN0X3R5cGUsIHRyaWFsX251bSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4odGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludCh0aHJvd19kZXZpYXRpb24pLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IHRyaWFsX251bSwgeSA9IG1lYW5fZGV2aWF0aW9uLCBjb2xvdXIgPSBleHBlcmltZW50DQogICAgKQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgIyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicygNCiAgICB4ID0gIlRyaWFsIE51bWJlciIsDQogICAgeSA9ICJUaHJvdyBBbmdsZSAowrApIg0KICApICsgIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAsIC0zMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygtMTUpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkgKyAjIHNldCBmb250IHNpemUgdG8gMTENCiAgdGhlbWUoDQogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpDQogICkgKyAjIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCiAgZ2VvbV9yaWJib24oDQogIGFlcygNCiAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uLA0KICAgIGZpbGwgPSBleHBlcmltZW50DQogICksDQogIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KICApICsgDQogIGdlb21fbGluZSgpICsgIyBzZXQgY29sb3VyIHBhbGV0dGUNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KDQojIHANCmBgYA0KIyMjIFRyaWFsIHNldHMgb2YgaW50ZXJlc3Qgb25seQ0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBmaWx0ZXIgb3V0IGp1c3QgdGhlIHRyaWFscyBvZiBpbnRlcmVzdA0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGZpbHRlcigNCiAgICB0ZXN0X3R5cGUgIT0gIm90aGVyIg0KICApDQojIGFkZCBhIGR1bW15IGNvbHVtbiB3aXRoIHJlcGVhdGluZyBzZXF1ZW5jZQ0KIyBOT1RFOiB0aGlzIGNhbid0IGJlIGNvbWJpbmVkIHdpdGggYWJvdmUgc2luY2Ugd2UgYXJlIHVzaW5nIG5yb3cNCmRhdGFfcGVyX2dyb3VwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBtdXRhdGUoZHVtbXlfeCA9IHJlcCgxOihucm93KGRhdGFfcGVyX2dyb3VwKSAvIG51bV9leHBzKSwNCiAgICBsZW5ndGgub3V0ID0gbnJvdyhkYXRhX3Blcl9ncm91cCkNCiAgKSkNCg0KIyBzZXQgdXAgcGxvdA0KcCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSBkdW1teV94LCB5ID0gbWVhbl9kZXZpYXRpb24sIGNvbG91ciA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIlRocm93IEFuZ2xlICjCsCkiDQogICkgKyAjIGFkZCBob3Jpem9udGFsIGxpbmVzDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMCwgLTMwKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAic29saWQiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKC0xNSksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKSArICMgc2V0IGNvbG91ciBwYWxldHRlDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkNCg0KIyBhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMgYW5kIGRhdGEgcG9pbnRzDQpmb3IgKHVuaXF1ZV90ZXN0X3R5cGUgaW4gdW5pcXVlKGRhdGFfcGVyX2dyb3VwJHRlc3RfdHlwZSkpIHsNCiAgIyBnZXQgdGhlIGRhdGEgZm9yIHRoaXMgYmxvY2sNCiAgdG9fcGxvdF9kYXRhIDwtIGZpbHRlcihkYXRhX3Blcl9ncm91cCwgdGVzdF90eXBlID09IHVuaXF1ZV90ZXN0X3R5cGUpDQoNCiAgcCA8LSBwICsgZ2VvbV9yaWJib24oDQogICAgZGF0YSA9IHRvX3Bsb3RfZGF0YSwNCiAgICBhZXMoDQogICAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgICB5bWF4ID0gbWVhbl9kZXZpYXRpb24gKyBjaV9kZXZpYXRpb24sDQogICAgICBmaWxsID0gZXhwZXJpbWVudA0KICAgICksIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KICApICsgZ2VvbV9saW5lKA0KICAgIGRhdGEgPSB0b19wbG90X2RhdGENCiAgKQ0KfQ0KDQoNCg0KZ2dwbG90bHkocCkNCmBgYA0KIyBOT1JNQUxJWkVEIEFOR1VMQVIgREVWSUFUSU9OUyAoaGFuZCBhbmdsZXMpDQojIyMgQWxsIFRyaWFscw0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyByZXN0IG9mIHRoZSBleHBzDQpkYXRhX3Blcl9ncm91cCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwX2xhYmVsID09ICJvcmlnaW5hbF9leHBzIiB8IGV4cF9sYWJlbCA9PSAiY3VydmVkX3BhdGgiKSAlPiUNCiAgZ3JvdXBfYnkoZXhwZXJpbWVudCwgdGVzdF90eXBlLCB0cmlhbF9udW0pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbWVhbl9kZXZpYXRpb24gPSBtZWFuKG5vcm1fdGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludChub3JtX3Rocm93X2RldmlhdGlvbiksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtLCB5ID0gbWVhbl9kZXZpYXRpb24sIGNvbG91ciA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIk5vcm1hbGl6ZWQgVGhyb3cgQW5nbGUiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAxLCAyKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAic29saWQiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAuNSwgMS41KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCnAgPC0gcCArIGdlb21fcmliYm9uKA0KICBhZXMoDQogICAgeW1pbiA9IG1lYW5fZGV2aWF0aW9uIC0gY2lfZGV2aWF0aW9uLA0KICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICBmaWxsID0gZXhwZXJpbWVudA0KICApLA0KICBjb2xvdXIgPSBOQSwgYWxwaGEgPSAwLjMNCikgKyBnZW9tX2xpbmUoKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KDQojIHANCmBgYA0KIyMjIFRyaWFsIHNldHMgb2YgaW50ZXJlc3Qgb25seQ0KTm90ZTogQmx1ZXMgPSBBY2NlbGVyYXRpb24gUGVydHVyYmF0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBmaWx0ZXIgb3V0IGp1c3QgdGhlIHRyaWFscyBvZiBpbnRlcmVzdA0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGZpbHRlcigNCiAgICB0ZXN0X3R5cGUgIT0gIm90aGVyIg0KICApDQoNCiMgYWRkIGEgZHVtbXkgY29sdW1uIHdpdGggcmVwZWF0aW5nIHNlcXVlbmNlDQojIE5PVEU6IHRoaXMgY2FuJ3QgYmUgY29tYmluZWQgd2l0aCBhYm92ZSBzaW5jZSB3ZSBhcmUgdXNpbmcgbnJvdw0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIG11dGF0ZShkdW1teV94ID0gcmVwKDE6KG5yb3coZGF0YV9wZXJfZ3JvdXApIC8gbnVtX2V4cHMpLA0KICAgIGxlbmd0aC5vdXQgPSBucm93KGRhdGFfcGVyX2dyb3VwKQ0KICApKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IGR1bW15X3gsIHkgPSBtZWFuX2RldmlhdGlvbiwgY29sb3VyID0gZXhwZXJpbWVudA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiTm9ybWFsaXplZCBUaHJvdyBBbmdsZSINCiAgKSArICMgYWRkIGhvcml6b250YWwgbGluZXMNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAxLCAyKSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAic29saWQiDQogICkgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAuNSwgMS41KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApICsgIyBzZXQgY29sb3VyIHBhbGV0dGUNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCmZvciAodW5pcXVlX3Rlc3RfdHlwZSBpbiB1bmlxdWUoZGF0YV9wZXJfZ3JvdXAkdGVzdF90eXBlKSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX2dyb3VwLCB0ZXN0X3R5cGUgPT0gdW5pcXVlX3Rlc3RfdHlwZSkNCg0KICBwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgICBkYXRhID0gdG9fcGxvdF9kYXRhLA0KICAgIGFlcygNCiAgICAgIHltaW4gPSBtZWFuX2RldmlhdGlvbiAtIGNpX2RldmlhdGlvbiwNCiAgICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICAgIGZpbGwgPSBleHBlcmltZW50DQogICAgKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQogICkgKyBnZW9tX2xpbmUoDQogICAgZGF0YSA9IHRvX3Bsb3RfZGF0YQ0KICApDQp9DQoNCg0KDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCiMjIEV4cG9uZW50aWFsIERlY2F5IEZpdHMgZm9yIHRoZSBMZWFybmluZyBhbmQgV2FzaG91dCBQaGFzZXMNCiMjIyBMZWFybmluZyBSYXRlcw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KZGF0YV9wZXJfcHB0IDwtIGluaXRfbGVhcm5pbmdfcmF0ZXMgJT4lDQogIGZpbHRlcigNCiAgICBleHBlcmltZW50ICE9ICJhX2JhbGxfcm9sbF9hbmltYXRlX3N1cmZhY2UiLA0KICAgIHRlc3RfdHlwZSAhPSAidHJhbnNmZXJfaW5pdCINCiAgKQ0KDQpkYXRhX3Blcl9ncm91cCA8LSBkYXRhX3Blcl9wcHQgJT4lDQogIGdyb3VwX2J5KGV4cGVyaW1lbnQsIHRlc3RfdHlwZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2xlYXJuaW5nX3JhdGUgPSBtZWFuKGV4cF9maXRfbGFtYmRhKSwNCiAgICBjaV9sZWFybmluZ19yYXRlID0gdmVjdG9yX2NvbmZpbnQoZXhwX2ZpdF9sYW1iZGEpLA0KICAgIG1lYW5faGlnaCA9IG1lYW4oZXhwX2ZpdF9OMCksDQogICAgY2lfaGlnaCA9IHZlY3Rvcl9jb25maW50KGV4cF9maXRfTjApLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKHggPSBleHBlcmltZW50LCB5ID0gbWVhbl9sZWFybmluZ19yYXRlLCBjb2xvdXIgPSBleHBlcmltZW50KQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIkxlYXJuaW5nIFJhdGUiDQogICkgKw0KICBmYWNldF93cmFwKA0KICAgIH50ZXN0X3R5cGUNCiAgKSArICMgcmVtb3ZlIGFsbCB4IGF4aXMgbGFiZWxzDQogIHRoZW1lKA0KICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKQ0KICApICsgIyBjb2xvdXIgbGVnZW5kIHNldHRpbmdzDQogIGd1aWRlcygNCiAgY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkNCiAgKSArICMgc2V0IGNvbG91ciBwYWxldHRlDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IHBhbGxldGVfbGlzdA0KICAgICkgKyAjIGFkZCBkYXRhIHBvaW50cw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGRhdGEgPSBkYXRhX3Blcl9wcHQsDQogICAgYWVzKA0KICAgICAgeSA9IGV4cF9maXRfbGFtYmRhDQogICAgKSwNCiAgICBhbHBoYSA9IDAuMSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKA0KICAgIHltaW4gPSBtZWFuX2xlYXJuaW5nX3JhdGUgLSBjaV9sZWFybmluZ19yYXRlLA0KICAgIHltYXggPSBtZWFuX2xlYXJuaW5nX3JhdGUgKyBjaV9sZWFybmluZ19yYXRlDQogICksIGFscGhhID0gMC41LCBsd2QgPSAyKSArDQogIGdlb21fcG9pbnQoKQ0KDQpnZ3Bsb3RseShwKQ0KIyBwDQpgYGANCg0KIyMjIEhpZ2ggUG9pbnRzIChBc3ltcHRvdGVzIG9yIFN0YXJ0cykNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cGVyaW1lbnQsIHkgPSBtZWFuX2hpZ2gsIGNvbG91ciA9IGV4cGVyaW1lbnQpDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiSGlnaCBQb2ludCINCiAgKSArDQogIGZhY2V0X3dyYXAofnRlc3RfdHlwZSkgKyAjIHJlbW92ZSBhbGwgeCBheGlzIGxhYmVscw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICAjIGZvciB0aGUgY29sb3VyIGxlZ2VuZCwgb25seSBzaG93IHRoZSBmaXJzdCA3DQogICMgTm90ZSB0aGlzIGRvZXNuJ3Qgd29yayBmb3IgdGhlIHBsb3RseSBwbG90DQogIGd1aWRlcygNCiAgY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkNCiAgKSsgIyBzZXQgY29sb3VyIHBhbGV0dGUNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogICMgYWRkIGRhdGEgcG9pbnRzDQogIGdlb21fYmVlc3dhcm0oDQogICAgZGF0YSA9IGRhdGFfcGVyX3BwdCwNCiAgICBhZXMoDQogICAgICB5ID0gZXhwX2ZpdF9OMA0KICAgICksDQogICAgYWxwaGEgPSAwLjEsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gbWVhbl9oaWdoIC0gY2lfaGlnaCwNCiAgICB5bWF4ID0gbWVhbl9oaWdoICsgY2lfaGlnaA0KICApLCBhbHBoYSA9IDAuNSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkNCg0KZ2dwbG90bHkocCkNCiMgcA0KYGBgDQpGb3Igd2FzaG91dDogVGhlIENVRUQgYWNjZWwgKyBjdXJ2ZWQgaGF2ZSBhIGxvd2VyIHN0YXJ0aW5nIHBvaW50ICh0aGVyZWZvcmUgLS0gY3VlIHdvcmtzKS4gVk1SIGdyb3VwIGhhcyBzbGlnaHRseSBsb3dlci4NCldoZW4gY29tcGFyaW5nIGV2ZXJ5dGhpbmcgd2l0aCBhIGhpZ2ggc3RhcnRpbmcgcG9pbnQsIHRoZSAgQUNDRUwgZ3JvdXAgaGFzIGEgbXVjaCBGQVNURVIgbGVhcm5pbmcgcmF0ZS4gDQoNCiMjIyBIaWdoIFBvaW50cyB2IExlYXJuaW5nIFJhdGVzDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQojIENvbXBhcmUgbGVhcm5pbmcgcmF0ZXMgYW5kIGhpZ2ggcG9pbnRzDQpwIDwtIGRhdGFfcGVyX3BwdCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZXhwX2ZpdF9sYW1iZGEsIHkgPSBleHBfZml0X04wLCBjb2xvdXIgPSBleHBlcmltZW50KQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicygNCiAgICB4ID0gIkxlYXJuaW5nIFJhdGUiLA0KICAgIHkgPSAiSGlnaCBQb2ludCINCiAgKSArDQogIGZhY2V0X3dyYXAofnRlc3RfdHlwZSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KIyMgRXhwb25lbnRpYWwgRGVjYXkgRml0cyBmb3IgdGhlIFRyYW5zZmVyIFBoYXNlDQoNCiMjIyBMZWFybmluZyBSYXRlcw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KZGF0YV9wZXJfcHB0IDwtIGluaXRfbGVhcm5pbmdfcmF0ZXNfM3BhciAlPiUNCiAgZmlsdGVyKA0KICAgIGV4cGVyaW1lbnQgIT0gImFfYmFsbF9yb2xsX2FuaW1hdGVfc3VyZmFjZSIsDQogICAgdGVzdF90eXBlID09ICJ0cmFuc2Zlcl9pbml0Ig0KICApDQoNCmRhdGFfcGVyX2dyb3VwIDwtIGRhdGFfcGVyX3BwdCAlPiUNCiAgZ3JvdXBfYnkoZXhwZXJpbWVudCwgdGVzdF90eXBlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fbGVhcm5pbmdfcmF0ZSA9IG1lYW4oZXhwX2ZpdF9sYW1iZGEpLA0KICAgIGNpX2xlYXJuaW5nX3JhdGUgPSB2ZWN0b3JfY29uZmludChleHBfZml0X2xhbWJkYSksDQogICAgbWVhbl9oaWdoID0gbWVhbihleHBfZml0X04wKSwNCiAgICBjaV9oaWdoID0gdmVjdG9yX2NvbmZpbnQoZXhwX2ZpdF9OMCksDQogICAgbWVhbl9sb3cgPSBtZWFuKGV4cF9maXRfZGlzcGxhY2UpLA0KICAgIGNpX2xvdyA9IHZlY3Rvcl9jb25maW50KGV4cF9maXRfZGlzcGxhY2UpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKHggPSBleHBlcmltZW50LCB5ID0gbWVhbl9sZWFybmluZ19yYXRlLCBjb2xvdXIgPSBleHBlcmltZW50KQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIkxlYXJuaW5nIFJhdGUiDQogICkgKw0KICBmYWNldF93cmFwKH50ZXN0X3R5cGUpICsNCiAgIyByZW1vdmUgYWxsIHggYXhpcyBsYWJlbHMNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgIyBmb3IgdGhlIGNvbG91ciBsZWdlbmQsIG9ubHkgc2hvdyB0aGUgZmlyc3QgNw0KICAjIE5vdGUgdGhpcyBkb2Vzbid0IHdvcmsgZm9yIHRoZSBwbG90bHkgcGxvdA0KICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsNCiAgIyBhZGQgZGF0YSBwb2ludHMNCiAgZ2VvbV9iZWVzd2FybSgNCiAgICBkYXRhID0gZGF0YV9wZXJfcHB0LA0KICAgIGFlcygNCiAgICAgIHkgPSBleHBfZml0X2xhbWJkYQ0KICAgICksDQogICAgYWxwaGEgPSAwLjEsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gbWVhbl9sZWFybmluZ19yYXRlIC0gY2lfbGVhcm5pbmdfcmF0ZSwNCiAgICB5bWF4ID0gbWVhbl9sZWFybmluZ19yYXRlICsgY2lfbGVhcm5pbmdfcmF0ZQ0KICApLCBhbHBoYSA9IDAuNSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkgKw0KICAjIHNldCBjb2xvdXIgcGFsZXR0ZQ0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQojIHANCmBgYA0KIyMjIEhpZ2ggUG9pbnRzIChBc3ltcHRvdGVzKQ0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KcCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZXhwZXJpbWVudCwgeSA9IG1lYW5faGlnaCwgY29sb3VyID0gZXhwZXJpbWVudCkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnMoDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJIaWdoIFBvaW50IChBc3ltcHRvdGVzKSINCiAgKSArDQogIGZhY2V0X3dyYXAofnRlc3RfdHlwZSkgKw0KICAjIHJlbW92ZSBhbGwgeCBheGlzIGxhYmVscw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKw0KICAjIGZvciB0aGUgY29sb3VyIGxlZ2VuZCwgb25seSBzaG93IHRoZSBmaXJzdCA3DQogICMgTm90ZSB0aGlzIGRvZXNuJ3Qgd29yayBmb3IgdGhlIHBsb3RseSBwbG90DQogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKw0KICAjIGFkZCBkYXRhIHBvaW50cw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGRhdGEgPSBkYXRhX3Blcl9wcHQsDQogICAgYWVzKA0KICAgICAgeSA9IGV4cF9maXRfTjANCiAgICApLA0KICAgIGFscGhhID0gMC4xLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX2xpbmVyYW5nZShhZXMoDQogICAgeW1pbiA9IG1lYW5faGlnaCAtIGNpX2hpZ2gsDQogICAgeW1heCA9IG1lYW5faGlnaCArIGNpX2hpZ2gNCiAgKSwgYWxwaGEgPSAwLjUsIGx3ZCA9IDIpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgIyBzZXQgY29sb3VyIHBhbGV0dGUNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KIyBwDQpgYGANCg0KIyMjIExvdyBQb2ludHMgKFN0YXJ0cykNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cGVyaW1lbnQsIHkgPSBtZWFuX2xvdywgY29sb3VyID0gZXhwZXJpbWVudCkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnMoDQogICAgeCA9IE5VTEwsDQogICAgeSA9ICJMb3cgUG9pbnQgKFN0YXJ0cykiDQogICkgKw0KICBmYWNldF93cmFwKH50ZXN0X3R5cGUpDQoNCiMgcmVtb3ZlIGFsbCB4IGF4aXMgbGFiZWxzDQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KIyBmb3IgdGhlIGNvbG91ciBsZWdlbmQsIG9ubHkgc2hvdyB0aGUgZmlyc3QgNw0KIyBOb3RlIHRoaXMgZG9lc24ndCB3b3JrIGZvciB0aGUgcGxvdGx5IHBsb3QNCnAgPC0gcCArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkNCg0KIyBhZGQgZGF0YSBwb2ludHMNCnAgPC0gcCArDQogIGdlb21fYmVlc3dhcm0oDQogICAgZGF0YSA9IGRhdGFfcGVyX3BwdCwNCiAgICBhZXMoDQogICAgICB5ID0gZXhwX2ZpdF9kaXNwbGFjZQ0KICAgICksDQogICAgYWxwaGEgPSAwLjEsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gbWVhbl9sb3cgLSBjaV9sb3csDQogICAgeW1heCA9IG1lYW5fbG93ICsgY2lfbG93DQogICksIGFscGhhID0gMC41LCBsd2QgPSAyKSArDQogIGdlb21fcG9pbnQoKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KIyBwDQpgYGANCg0KV2hlbiB0cmFuc2ZlcnJpbmcsIHdoYXQgaGFwcGVucz8NCg0KIyMjIENvcnJlbGF0aW9ucyB3aXRoaW4gdGhlIDMgdmFyaWFibGVzIGFib3ZlDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIiwgd2FybmluZz1GQUxTRX0NCiMgM2QgcGxvdCBvZiBsZWFybmluZyByYXRlcywgaGlnaCBwb2ludHMsIGFuZCBsb3cgcG9pbnRzDQojIGZpbHRlciBvdXQganVzdCB0aGUgd2FzaG91dCB0cmlhbHMgZm9yIG5vdw0KZGF0YV9wZXJfcHB0IDwtIGluaXRfbGVhcm5pbmdfcmF0ZXNfM3BhciAlPiUNCiAgZmlsdGVyKHRlc3RfdHlwZSA9PSAidHJhbnNmZXJfaW5pdCIpDQoNCnAgPC0gcGxvdF9seSh0eXBlID0gInNjYXR0ZXIzZCIsIG1vZGUgPSAibWFya2VycyIpDQoNCmZvciAoZXhwZXJpbWVudF8gaW4gdW5pcXVlKGRhdGFfcGVyX3BwdCRleHBlcmltZW50KSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX3BwdCwgZXhwZXJpbWVudCA9PSBleHBlcmltZW50XykNCg0KICBwIDwtIHAgJT4lDQogICAgYWRkX3RyYWNlKA0KICAgICAgeCA9IHRvX3Bsb3RfZGF0YSRleHBfZml0X2xhbWJkYSwNCiAgICAgIHkgPSB0b19wbG90X2RhdGEkZXhwX2ZpdF9OMCwNCiAgICAgIHogPSB0b19wbG90X2RhdGEkZXhwX2ZpdF9kaXNwbGFjZSwNCiAgICAgIGNvbG9yID0gSShwYWxsZXRlX2xpc3RbZXhwZXJpbWVudF9dKSwNCiAgICAgIG5hbWUgPSBleHBlcmltZW50Xw0KICAgICkNCn0NCg0KIyBBeGVzIG5hbWVzDQpwIDwtIHAgJT4lIGxheW91dCgNCiAgc2NlbmUgPQ0KICAgIChsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkxlYXJuaW5nIFJhdGUiKSwNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJIaWdoIFBvaW50IiksDQogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiTG93IFBvaW50IiksDQogICAgICBhc3BlY3Rtb2RlID0gImN1YmUiICMgZXF1YWwgYXNwZWN0IHJhdGlvcw0KICAgICkpDQopDQoNCnANCmBgYA0KDQotIFdlIG1pZ2h0IHdhbnQgdG8gdGVzdCBpZiBkYXRhIHBvaW50cyBjbHVzdGVyIGRpZmZlcmVudGx5IGRlcGVuZGluZyBvbiB0aGUgZXhwZXJpbWVudCBjb25kaXRpb25zLg0KLSBOb3RlOiBJdCBpcyBhIGdvb2QgaWRlYSB0byBkbyBzb21lIEVEQSB0byBjaGVjayBpZiBhbGwgMyBkaW1lbnNpb25zIGFyZSByZXF1aXJlZC4gQ29ycmVsYXRpb24gbWF0cml4Pw0KDQoNCiMjIyBJbmlkaXZpZHVhbCBEYXRhIHdpdGhpbiAxIGdyb3VwDQpgYGB7cn0NCiMjIyBFcnJvciBTaXplICMjIw0KDQojIHJlc3Qgb2YgdGhlIGV4cHMNCmRhdGFfcGVyX3BwdCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwZXJpbWVudCA9PSAiYWNjZWxfdW5jdWVkIiwgdGVzdF90eXBlID09ICJ3YXNob3V0X2luaXQiKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX3BwdCAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcygNCiAgICAgIHggPSB0cmlhbF9udW0sIHkgPSBub3JtX3Rocm93X2RldmlhdGlvbiwgY29sb3VyID0gcHBpZA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiTm9ybWFsaXplZCBUaHJvdyBBbmdsZSINCiAgKQ0KDQojIGFkZCBob3Jpem9udGFsIGxpbmVzDQpwIDwtIHAgKw0KICBnZW9tX2hsaW5lKA0KICAgIHlpbnRlcmNlcHQgPSBjKDAsIDEsIDIpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMC41LCAxLjUpLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkNCg0KIyBzZXQgZm9udCBzaXplIHRvIDExDQpwIDwtIHAgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpDQoNCiMgYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBkYXRhIHBvaW50cw0KcCA8LSBwICsgZ2VvbV9saW5lKCkNCg0KZ2dwbG90bHkocCkNCg0KIyBwDQpgYGANCg0KIyBFUlJPUiBTSVpFDQpOb3RlOiBCbHVlcyA9IEFjY2VsZXJhdGlvbiBQZXJ0dXJiYXRpb25zDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQojIG9yaWdpbmFsIGV4cGVyaW1lbnRzIG9ubHkNCmRhdGFfcGVyX2dyb3VwIDwtIG9tbmlidXNfZGYgJT4lDQogIGZpbHRlcihleHBfbGFiZWwgPT0gIm9yaWdpbmFsX2V4cHMiIHwgZXhwX2xhYmVsID09ICJjdXJ2ZWRfcGF0aCIpICU+JQ0KICBncm91cF9ieShleHBlcmltZW50LCB0ZXN0X3R5cGUsIHRyaWFsX251bSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4oZXJyb3Jfc2l6ZSksDQogICAgY2lfZGV2aWF0aW9uID0gdmVjdG9yX2NvbmZpbnQoZXJyb3Jfc2l6ZSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtLCB5ID0gbWVhbl9kZXZpYXRpb24sIGNvbG91ciA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIkFic29sdXRlIFRhcmdldCBFcnJvciAoY20pIg0KICApDQoNCiMgYWRkIGhvcml6b250YWwgbGluZXMNCnAgPC0gcCArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMCwgNDApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoMjApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJkYXNoZWQiDQogICkNCg0KIyBzZXQgZm9udCBzaXplIHRvIDExDQpwIDwtIHAgKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpDQoNCiMgYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBkYXRhIHBvaW50cw0KcCA8LSBwICsgZ2VvbV9yaWJib24oDQogIGFlcygNCiAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uLA0KICAgIGZpbGwgPSBleHBlcmltZW50DQogICksDQogIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KKSArIGdlb21fbGluZSgpDQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQoNCiMgcA0KYGBgDQoNCnZpc2libGUgdnMgbm9uLXZpc2libGUgdGlsdCBkb2Vzbid0IGFmZmVjdCB0aGUgMTUtZGVncmVlIHJvdGF0aW9uIGNvbmRpdGlvbi4gQnV0IGFmZmVjdHMgYWxsIG90aGVyIGNvbmRpdGlvbnMuIFNvIDE1LWRlZ3JlZSByb3RhdGlvbg0KDQojIyMgVHJpYWwgc2V0cyBvZiBpbnRlcmVzdCBvbmx5DQpOb3RlOiBCbHVlcyA9IEFjY2VsZXJhdGlvbiBQZXJ0dXJiYXRpb25zDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQojIGZpbHRlciBvdXQganVzdCB0aGUgdHJpYWxzIG9mIGludGVyZXN0DQpkYXRhX3Blcl9ncm91cCA8LSBkYXRhX3Blcl9ncm91cCAlPiUNCiAgZmlsdGVyKA0KICAgIHRlc3RfdHlwZSAhPSAib3RoZXIiDQogICkNCiMgYWRkIGEgZHVtbXkgY29sdW1uIHdpdGggcmVwZWF0aW5nIHNlcXVlbmNlDQojIE5PVEU6IHRoaXMgY2FuJ3QgYmUgY29tYmluZWQgd2l0aCBhYm92ZSBzaW5jZSB3ZSBhcmUgdXNpbmcgbnJvdw0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIG11dGF0ZShkdW1teV94ID0gcmVwKDE6KG5yb3coZGF0YV9wZXJfZ3JvdXApIC8gbnVtX2V4cHMpLA0KICAgIGxlbmd0aC5vdXQgPSBucm93KGRhdGFfcGVyX2dyb3VwKQ0KICApKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IGR1bW15X3gsIHkgPSBtZWFuX2RldmlhdGlvbiwgY29sb3VyID0gZXhwZXJpbWVudA0KICAgICkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnMoDQogICAgeCA9ICJUcmlhbCBOdW1iZXIiLA0KICAgIHkgPSAiQWJzb2x1dGUgVGFyZ2V0IEVycm9yIChjbSkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCA0MCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gInNvbGlkIg0KICApICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygyMCksIGxpbmV3aWR0aCA9IDAuNCwNCiAgICBjb2xvdXIgPSAiI0NDQ0NDQyIsIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKQ0KDQojIGFkZCBjb25maWRlbmNlIGludGVydmFscyBhbmQgZGF0YSBwb2ludHMNCmZvciAodW5pcXVlX3Rlc3RfdHlwZSBpbiB1bmlxdWUoZGF0YV9wZXJfZ3JvdXAkdGVzdF90eXBlKSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX2dyb3VwLCB0ZXN0X3R5cGUgPT0gdW5pcXVlX3Rlc3RfdHlwZSkNCg0KICBwIDwtIHAgKyBnZW9tX3JpYmJvbigNCiAgICBkYXRhID0gdG9fcGxvdF9kYXRhLA0KICAgIGFlcygNCiAgICAgIHltaW4gPSBtZWFuX2RldmlhdGlvbiAtIGNpX2RldmlhdGlvbiwNCiAgICAgIHltYXggPSBtZWFuX2RldmlhdGlvbiArIGNpX2RldmlhdGlvbiwNCiAgICAgIGZpbGwgPSBleHBlcmltZW50DQogICAgKSwgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQogICkgKyBnZW9tX2xpbmUoDQogICAgZGF0YSA9IHRvX3Bsb3RfZGF0YQ0KICApDQp9DQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KDQoNCiMgQW5pbWF0ZWQgU3VyZmFjZSBGb2xsb3ctdXANCg0KIyMjIFBsb3QgQU5HVUxBUiBERVZJQVRJT05TIChoYW5kIGFuZ2xlcykNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCiMgaXNvbGF0ZSBhbmltYXRlX3N1cmZhY2UgZXhwDQpkYXRhX3Blcl9ncm91cCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoZXhwX2xhYmVsID09ICJhbmltYXRlX3N1cmZhY2UiKSAlPiUNCiAgZ3JvdXBfYnkocHJpb3JfYW5pbSwgYmxvY2tfbnVtLCB0cmlhbF9udW1faW5fYmxvY2ssIHRyaWFsX251bSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4odGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludCh0aHJvd19kZXZpYXRpb24pDQogICkNCg0KIyBvcmRlciB0aGUgZmFjdG9ycyBmb3IgYXNzaWduaW5nIGNvbG91ciBwYWxsZXRzDQpkYXRhX3Blcl9ncm91cCRwcmlvcl9hbmltIDwtIGZhY3RvcigNCiAgZGF0YV9wZXJfZ3JvdXAkcHJpb3JfYW5pbSwNCiAgbGV2ZWxzID0gYygNCiAgICAibm9uZSIsICJoYWxmX2FuaW0iLCAiZnVsbF9hbmltIg0KICApDQopDQoNCiMgc2V0IHVwIHBsb3QNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoDQogICAgICB4ID0gdHJpYWxfbnVtLCB5ID0gbWVhbl9kZXZpYXRpb24sDQogICAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgICB5bWF4ID0gbWVhbl9kZXZpYXRpb24gKyBjaV9kZXZpYXRpb24NCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIiwNCiAgICB5ID0gIlRocm93IEFuZ2xlICjCsCkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAtMzApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgc2V0IGZvbnQgc2l6ZSB0byAxMQ0KcCA8LSBwICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQ0KDQojIHJlcGVhdCBmb3IgcHJpb3JfYW5pbSA9PSAiaGFsZiIsICJmdWxsIiBhbmQgIndhaXQiDQpmb3IgKHVuaXF1ZV9wcmlvcl9hbmltIGluIHVuaXF1ZShkYXRhX3Blcl9ncm91cCRwcmlvcl9hbmltKSkgew0KICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICB0b19wbG90X2RhdGEgPC0gZmlsdGVyKGRhdGFfcGVyX2dyb3VwLCBwcmlvcl9hbmltID09IHVuaXF1ZV9wcmlvcl9hbmltKQ0KICAjIGxvb3AgdGhyb3VnaCB0aGUgdW5pcXVlIGJsb2NrcyBpbiB0b19wbG90X2RhdGENCiAgZm9yIChibG9jayBpbiB1bmlxdWUodG9fcGxvdF9kYXRhJGJsb2NrX251bSkpIHsNCiAgICAjIGdldCB0aGUgZGF0YSBmb3IgdGhpcyBibG9jaw0KICAgIGJsb2NrX2RhdGEgPC0gZmlsdGVyKHRvX3Bsb3RfZGF0YSwgYmxvY2tfbnVtID09IGJsb2NrKQ0KICAgICMgYWRkIHRoZSBkYXRhLCB1c2UgdGhlIHBhbGxldGVfbGlzdCB0byBnZXQgdGhlIGNvbG91cg0KICAgIHAgPC0gcCArIGdlb21fcmliYm9uKA0KICAgICAgZGF0YSA9IGJsb2NrX2RhdGEsDQogICAgICBhZXMoZmlsbCA9IHByaW9yX2FuaW0pLA0KICAgICAgY29sb3VyID0gTkEsIGFscGhhID0gMC4zDQogICAgKSArIGdlb21fbGluZSgNCiAgICAgIGRhdGEgPSBibG9ja19kYXRhLA0KICAgICAgYWVzKGNvbG91ciA9IHByaW9yX2FuaW0pDQogICAgKQ0KICB9DQp9DQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQojIHANCmBgYA0KDQojIyMgV2FzaG91dCB0cmlhbHMgYWZ0ZXIgaGFsZiBWUyBmdWxsIGFuaW1hdGlvbnMNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSIxMDAlIn0NCiMgZmlyc3QsIGlzb2xhdGUgdGhlIGRhdGENCmRhdGFfcGVyX3BwdF9hbmltIDwtIG9tbmlidXNfZGYgJT4lDQogIGZpbHRlcigNCiAgICBleHBfbGFiZWwgPT0gImFuaW1hdGVfc3VyZmFjZSIsDQogICAgYmFzZWxpbmVfYmxvY2sgPT0gRkFMU0UsDQogICAgdGVzdF90eXBlID09ICJ3YXNob3V0X2FuaW0iDQogICkgJT4lDQogIGdyb3VwX2J5KHBwaWQsIHByaW9yX2FuaW0sIHRyaWFsX251bV9pbl9ibG9jaykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBwcHRfbWVkaWFuX2RldmlhdGlvbiA9IG1lZGlhbih0aHJvd19kZXZpYXRpb24pLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKSAlPiUgIyBwcmlvcl9hbmltIHJlbmFtZSB0byBleHBlcmltZW50ICh0byBtYXRjaCB0aGUgb3RoZXIgY29tcGFyaXNvbnMpDQogIG11dGF0ZSgNCiAgICBleHBlcmltZW50ID0gcHJpb3JfYW5pbSwNCiAgICB0aHJvd19kZXZpYXRpb24gPSBwcHRfbWVkaWFuX2RldmlhdGlvbg0KICApICU+JQ0KICBzZWxlY3QoLXByaW9yX2FuaW0sIC1wcHRfbWVkaWFuX2RldmlhdGlvbikNCg0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfcHB0X2FuaW0gJT4lDQogIGdyb3VwX2J5KGV4cGVyaW1lbnQsIHRyaWFsX251bV9pbl9ibG9jaykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4odGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludCh0aHJvd19kZXZpYXRpb24pLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIHNldCB1cCBwbG90DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKA0KICAgICAgeCA9IHRyaWFsX251bV9pbl9ibG9jaywgeSA9IG1lYW5fZGV2aWF0aW9uLA0KICAgICAgY29sb3VyID0gZXhwZXJpbWVudCwgZmlsbCA9IGV4cGVyaW1lbnQNCiAgICApDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKA0KICAgIHggPSAiVHJpYWwgTnVtYmVyIGluIEJsb2NrIiwNCiAgICB5ID0gIlRocm93IEFuZ2xlICjCsCkiDQogICkNCg0KIyBhZGQgaG9yaXpvbnRhbCBsaW5lcw0KcCA8LSBwICsNCiAgZ2VvbV9obGluZSgNCiAgICB5aW50ZXJjZXB0ID0gYygwLCAtMzApLCBsaW5ld2lkdGggPSAwLjQsDQogICAgY29sb3VyID0gIiNDQ0NDQ0MiLCBsaW5ldHlwZSA9ICJzb2xpZCINCiAgKSArDQogIGdlb21faGxpbmUoDQogICAgeWludGVyY2VwdCA9IGMoLTE1KSwgbGluZXdpZHRoID0gMC40LA0KICAgIGNvbG91ciA9ICIjQ0NDQ0NDIiwgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApDQoNCiMgYWRkIGRhdGEgcG9pbnRzDQpwIDwtIHAgKw0KICBnZW9tX3JpYmJvbigNCiAgICBhZXMoDQogICAgICB5bWluID0gbWVhbl9kZXZpYXRpb24gLSBjaV9kZXZpYXRpb24sDQogICAgICB5bWF4ID0gbWVhbl9kZXZpYXRpb24gKyBjaV9kZXZpYXRpb24NCiAgICApLA0KICAgIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KICApICsNCiAgZ2VvbV9saW5lKCkNCg0KIyBhZGQgd2FzaG91dF9pbml0IGZyb20gdGhlIDMwLWRlZ3JlZSByb3RhdGlvbiBjb25kaXRpb24NCmRhdGFfcGVyX3BwdF8zMCA8LSBvbW5pYnVzX2RmICU+JQ0KICBmaWx0ZXIoDQogICAgZXhwZXJpbWVudCAlaW4lIGMoInJvdDMwX2N1ZWRfdGlsdCIsICJyb3QzMF91bmN1ZWQiKSwNCiAgICB0ZXN0X3R5cGUgPT0gIndhc2hvdXRfaW5pdCIsDQogICAgdHJpYWxfbnVtX2luX2Jsb2NrIDw9IDgNCiAgKSAlPiUNCiAgc2VsZWN0KHBwaWQsIHRyaWFsX251bV9pbl9ibG9jaywgZXhwZXJpbWVudCwgdGhyb3dfZGV2aWF0aW9uKQ0KDQpkYXRhX3Blcl9ncm91cF8zMCA8LSBkYXRhX3Blcl9wcHRfMzAgJT4lDQogIGdyb3VwX2J5KGV4cGVyaW1lbnQsIHRyaWFsX251bV9pbl9ibG9jaykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX2RldmlhdGlvbiA9IG1lYW4odGhyb3dfZGV2aWF0aW9uKSwNCiAgICBjaV9kZXZpYXRpb24gPSB2ZWN0b3JfY29uZmludCh0aHJvd19kZXZpYXRpb24pLA0KICAgIG4gPSBuKCksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgYWRkIGRhdGEgcG9pbnRzDQpwIDwtIHAgKw0KICBnZW9tX3JpYmJvbigNCiAgICBkYXRhID0gZGF0YV9wZXJfZ3JvdXBfMzAsDQogICAgYWVzKA0KICAgICAgeW1pbiA9IG1lYW5fZGV2aWF0aW9uIC0gY2lfZGV2aWF0aW9uLA0KICAgICAgeW1heCA9IG1lYW5fZGV2aWF0aW9uICsgY2lfZGV2aWF0aW9uLA0KICAgICAgZmlsbCA9IGV4cGVyaW1lbnQNCiAgICApLA0KICAgIGNvbG91ciA9IE5BLCBhbHBoYSA9IDAuMw0KICApICsNCiAgZ2VvbV9saW5lKA0KICAgIGRhdGEgPSBkYXRhX3Blcl9ncm91cF8zMCwNCiAgICBhZXMoDQogICAgICBjb2xvdXIgPSBleHBlcmltZW50DQogICAgKQ0KICApDQoNCiMgc2V0IGNvbG91ciBwYWxldHRlDQpwIDwtIHAgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KYGBge3J9DQojIHJiaW5kIGRhdGFfcGVyX3BwdF9hbmltIGFuZCBkYXRhX3Blcl9wcHRfMzANCmFuaW1fY29tcGFyaXNvbl9kZiA8LSByYmluZCgNCiAgZGF0YV9wZXJfcHB0X2FuaW0sDQogIGRhdGFfcGVyX3BwdF8zMA0KKQ0KDQojIHJlbW92ZSBkYXRhX3Blcl9wcHRfYW5pbSBhbmQgZGF0YV9wZXJfcHB0XzMwDQpybShkYXRhX3Blcl9wcHRfYW5pbSwgZGF0YV9wZXJfcHB0XzMwKQ0KDQojIE9wdGlvbmFsbHkgY29tcHV0ZSBsZWFybmluZyByYXRlIGZpdHMNCiMgRG8gaWYgbGVhcm5pbmdfcmF0ZV9kZl9hbmltLmNzdiBkb2Vzbid0IGV4aXN0IGluIC4uL2RhdGEvcHJvY2Vzc2VkDQppZiAoIWZpbGUuZXhpc3RzKCIuLi9kYXRhL3Byb2Nlc3NlZC9sZWFybmluZ19yYXRlX2RmX2FuaW0uY3N2IikpIHsNCiAgcHJpbnQoU3lzLnRpbWUoKSkNCiAgYXBwbHlfZXhwb25lbnRpYWxfZml0IDwtIGZ1bmN0aW9uKGRmKSB7DQogICAgZGYgJT4lDQogICAgICBzdW1tYXJpc2UoDQogICAgICAgIHBwaWQgPSBmaXJzdChwcGlkKSwNCiAgICAgICAgZXhwZXJpbWVudCA9IGZpcnN0KGV4cGVyaW1lbnQpLA0KICAgICAgICBleHBvbmVudGlhbEZpdCA9IGV4cG9uZW50aWFsRml0KHRocm93X2RldmlhdGlvbiwNCiAgICAgICAgICBtb2RlID0gIndhc2hvdXRfaW5pdCINCiAgICAgICAgKQ0KICAgICAgKQ0KICB9DQoNCiAgYW5pbV9sZWFybmluZ19yYXRlcyA8LSBhbmltX2NvbXBhcmlzb25fZGYgJT4lDQogICAgZ3JvdXBfYnkocHBpZCwgZXhwZXJpbWVudCkgJT4lDQogICAgZ3JvdXBfc3BsaXQoKSAlPiUNCiAgICBmdXR1cmVfbWFwKGFwcGx5X2V4cG9uZW50aWFsX2ZpdCkgJT4lDQogICAgYmluZF9yb3dzKCkgJT4lDQogICAgdW5uZXN0KGNvbHMgPSBjKCJleHBvbmVudGlhbEZpdCIpKQ0KDQogIHByaW50KCJkb25lIDIgcGFyYW0gZml0cyIpDQogIHByaW50KFN5cy50aW1lKCkpDQoNCiAgd3JpdGVfY3N2KA0KICAgIGFuaW1fbGVhcm5pbmdfcmF0ZXMsDQogICAgIi4uL2RhdGEvcHJvY2Vzc2VkL2xlYXJuaW5nX3JhdGVfZGZfYW5pbS5jc3YiDQogICkNCn0gZWxzZSB7DQogIGFuaW1fbGVhcm5pbmdfcmF0ZXMgPC0gcmVhZF9jc3YoDQogICAgIi4uL2RhdGEvcHJvY2Vzc2VkL2xlYXJuaW5nX3JhdGVfZGZfYW5pbS5jc3YiLA0KICAgIGNvbF90eXBlcyA9IGNvbHMoDQogICAgICAuZGVmYXVsdCA9IGNvbF9kb3VibGUoKSwNCiAgICAgIHBwaWQgPSBjb2xfZmFjdG9yKCksDQogICAgICBleHBlcmltZW50ID0gY29sX2ZhY3RvcigpDQogICAgKQ0KICApDQp9DQpgYGANCiMjIyBMZWFybmluZyBSYXRlcw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KZGF0YV9wZXJfcHB0IDwtIGFuaW1fbGVhcm5pbmdfcmF0ZXMNCg0KZGF0YV9wZXJfZ3JvdXAgPC0gZGF0YV9wZXJfcHB0ICU+JQ0KICBncm91cF9ieShleHBlcmltZW50KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fbGVhcm5pbmdfcmF0ZSA9IG1lYW4oZXhwX2ZpdF9sYW1iZGEpLA0KICAgIGNpX2xlYXJuaW5nX3JhdGUgPSB2ZWN0b3JfY29uZmludChleHBfZml0X2xhbWJkYSksDQogICAgbWVhbl9oaWdoID0gbWVhbihleHBfZml0X04wKSwNCiAgICBjaV9oaWdoID0gdmVjdG9yX2NvbmZpbnQoZXhwX2ZpdF9OMCksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCnAgPC0gZGF0YV9wZXJfZ3JvdXAgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cGVyaW1lbnQsIHkgPSBtZWFuX2xlYXJuaW5nX3JhdGUsIGNvbG91ciA9IGV4cGVyaW1lbnQpDQogICkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKA0KICAgIHggPSBOVUxMLA0KICAgIHkgPSAiTGVhcm5pbmcgUmF0ZSINCiAgKQ0KDQojIHJlbW92ZSBhbGwgeCBheGlzIGxhYmVscw0KcCA8LSBwICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpDQoNCiMgZm9yIHRoZSBjb2xvdXIgbGVnZW5kLCBvbmx5IHNob3cgdGhlIGZpcnN0IDcNCiMgTm90ZSB0aGlzIGRvZXNuJ3Qgd29yayBmb3IgdGhlIHBsb3RseSBwbG90DQpwIDwtIHAgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpDQoNCiMgYWRkIGRhdGEgcG9pbnRzDQpwIDwtIHAgKw0KICBnZW9tX2JlZXN3YXJtKA0KICAgIGRhdGEgPSBkYXRhX3Blcl9wcHQsDQogICAgYWVzKA0KICAgICAgeSA9IGV4cF9maXRfbGFtYmRhDQogICAgKSwNCiAgICBhbHBoYSA9IDAuMSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKA0KICAgIHltaW4gPSBtZWFuX2xlYXJuaW5nX3JhdGUgLSBjaV9sZWFybmluZ19yYXRlLA0KICAgIHltYXggPSBtZWFuX2xlYXJuaW5nX3JhdGUgKyBjaV9sZWFybmluZ19yYXRlDQogICksIGFscGhhID0gMC41LCBsd2QgPSAyKSArDQogIGdlb21fcG9pbnQoKQ0KDQojIHNldCBjb2xvdXIgcGFsZXR0ZQ0KcCA8LSBwICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KQ0KDQpnZ3Bsb3RseShwKQ0KIyBwDQpgYGANCg0KIyMjIEhpZ2ggUG9pbnRzIChTdGFydHMpDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTYsIG91dC53aWR0aD0iMTAwJSJ9DQpwIDwtIGRhdGFfcGVyX2dyb3VwICU+JQ0KICBnZ3Bsb3QoDQogICAgYWVzKHggPSBleHBlcmltZW50LCB5ID0gbWVhbl9oaWdoLCBjb2xvdXIgPSBleHBlcmltZW50KQ0KICApICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicygNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIlN0YXJ0IFBvaW50Ig0KICApDQoNCiMgcmVtb3ZlIGFsbCB4IGF4aXMgbGFiZWxzDQpwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KIyBmb3IgdGhlIGNvbG91ciBsZWdlbmQsIG9ubHkgc2hvdyB0aGUgZmlyc3QgNw0KIyBOb3RlIHRoaXMgZG9lc24ndCB3b3JrIGZvciB0aGUgcGxvdGx5IHBsb3QNCnAgPC0gcCArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkNCg0KIyBhZGQgZGF0YSBwb2ludHMNCnAgPC0gcCArDQogIGdlb21fYmVlc3dhcm0oDQogICAgZGF0YSA9IGRhdGFfcGVyX3BwdCwNCiAgICBhZXMoDQogICAgICB5ID0gZXhwX2ZpdF9OMA0KICAgICksDQogICAgYWxwaGEgPSAwLjEsDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fbGluZXJhbmdlKGFlcygNCiAgICB5bWluID0gbWVhbl9oaWdoIC0gY2lfaGlnaCwNCiAgICB5bWF4ID0gbWVhbl9oaWdoICsgY2lfaGlnaA0KICApLCBhbHBoYSA9IDAuNSwgbHdkID0gMikgKw0KICBnZW9tX3BvaW50KCkNCg0KIyBzZXQgY29sb3VyIHBhbGV0dGUNCnAgPC0gcCArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsbGV0ZV9saXN0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkNCg0KZ2dwbG90bHkocCkNCiMgcA0KYGBgDQojIyMgSGlnaCBQb2ludHMgdiBMZWFybmluZyBSYXRlcw0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjEwMCUifQ0KIyBDb21wYXJlIGxlYXJuaW5nIHJhdGVzIGFuZCBoaWdoIHBvaW50cw0KcCA8LSBkYXRhX3Blcl9wcHQgJT4lDQogIGdncGxvdCgNCiAgICBhZXMoeCA9IGV4cF9maXRfbGFtYmRhLCB5ID0gZXhwX2ZpdF9OMCwgY29sb3VyID0gZXhwZXJpbWVudCkNCiAgKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIGxhYnMoDQogICAgeCA9ICJMZWFybmluZyBSYXRlIiwNCiAgICB5ID0gIkhpZ2ggUG9pbnQgKFN0YXJ0cykiDQogICkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGxldGVfbGlzdCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxsZXRlX2xpc3QpDQoNCmdncGxvdGx5KHApDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0KIyMgRU1QVFkNCmBgYA0KDQoNCiMgRGVwcmVjYXRlZCAoRG9uJ3QgUnVuKQ0KDQojIyBTdWNjZXNzIG1hbmlmb2xkcw0KIyMjIFdpdGhvdXQgYW55IHRpbHRzDQpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MjB9DQpwbG90X3N1Y2Nlc3NfbWFuaWZvbGRfbm9fdGlsdCgpDQpgYGANCg0KIyMjIFdpdGggdGlsdCBwcmVzZW50DQpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MjB9DQpwbG90X3N1Y2Nlc3NfbWFuaWZvbGRfdGlsdCgpDQpgYGANCg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCk5VTEwNCmBgYA0KDQo=